/*
 Notes on utilizing the Nordic nRF24AP1 ANT module from a TI MSP430
  - This example specifically uses the MSPF249 on the OLIMEX MSP430-P249 board.
  - Using the Sparkfun module (part #WRL-08565) set to 4800bps.
  - Using UCSI_A1 as my UART because UCSI_A0 is hard wired to the RS232 port

 Copyright Matt Stump 2009.
*/

#include "io430.h"
#include <stdio.h>
#include <cstring>
#include <signal.h>
#include <intrinsics.h>

typedef unsigned char uchar;

uchar	txBuffer[256];
size_t	txBufferSize;
size_t	txBufferPos;
int		state = 0;

void
txMessage(
   uchar*	message,
   size_t	messageSize)
{
	// disable interrupts
	__disable_interrupt();

	txBufferPos		= 0;							// set position to 0
	txBufferSize	= messageSize + 3;				// message plus syc, size and checksum
	txBuffer[0]		= 0xa4;							// sync byte
	txBuffer[1]		= (uchar) messageSize - 1;		// message size - command size (1)
	memcpy(&txBuffer[2], message, messageSize);		// copy the message to the buffer

	// calculate the checksum
	for (int i = 0; i < txBufferSize - 1; ++i)
		txBuffer[txBufferSize - 1] = txBuffer[txBufferSize - 1] ^ txBuffer[i];

	// reenable interrupts
	__enable_interrupt();
}

// Resets module
void 
reset() 
{
	uchar setup[2];
	setup[0] = 0x4a; // ID Byte
	setup[1] = 0x00; // Data Byte N (N=LENGTH)
	txMessage(setup, 2);
}

// Assigns CH=0, CH Type=10(TX), Net#=0
void 
assignch() 
{
	uchar setup[4];
	setup[0] = 0x42;
	setup[1] = 0x00;
	setup[2] = 0x10;
	setup[3] = 0x00;
	txMessage(setup, 4);
}

// Assigns Device#=0000, Device Type ID=00, Trans Type=00
void 
setchid() 
{
	uchar setup[6];
	setup[0] = 0x51;
	setup[1] = 0x00;
	setup[2] = 0x00;
	setup[3] = 0x00;
	setup[4] = 0x00;
	setup[5] = 0x00;
	txMessage(setup, 6);
}

// Opens CH 0
void 
opench() 
{
	uchar setup[2];
	setup[0] = 0x4b;
	setup[1] = 0x00;
	txMessage(setup, 2);
}

// Sends Data=AAAAAAAAAAAAAAAA
void
sendAAA() 
{
	uchar setup[10];
	setup[0] = 0x4e;
	setup[1] = 0x00;
	setup[2] = 0xaa;
	setup[3] = 0xaa;
	setup[4] = 0xaa;
	setup[5] = 0xaa;
	setup[6] = 0xaa;
	setup[7] = 0xaa;
	setup[8] = 0xaa;
	setup[9] = 0xaa;
	txMessage(setup, 10);
}

void
checkState()
{
	switch (state)
	{
		case 0:
			reset();
			break;

		case 1:
			assignch();
			break;

		case 2:
			setchid();
			break;

		case 3:
			opench();
			break;

		case 4:
			sendAAA();
			break;

		default:
			sendAAA();
			break;
	}

	++state;
}

int 
main()
{
	// stop watchdog timer to prevent time out reset
	WDTCTL				=	WDTPW + WDTHOLD;
	
	// set SCLK to calibrated 1 MHz DCO
	BCSCTL1				=	CALBC1_1MHZ;
	DCOCTL				=	CALDCO_1MHZ; 
	
	// setup ACLK source and parameters, external crystal is 32.768 kHz
	BCSCTL3				=	LFXT1S_0 | XT2S_0 |	 XCAP_1;
	
	// UART
	UCA1CTL1			=	UCSSEL_1 | UCSWRST;	// use ACLK as uart clock source, hold the UART
	UCA1CTL0			=	0;					// UART ASYNC MODE, 8N1, LSB
	
	// configure the ports
	P1DIR				=	0xFF;				// All P1.x outputs
	P1OUT				=	0;					// All P1.x reset
	P2DIR				=	0xFF;				// All P2.x outputs
	P2OUT				=	0;					// All P2.x reset
	P3SEL				=	0x60;				// P3.6,7 = USCI_A1 TXD/RXD
	P3DIR				=	0xFF;				// All P3.x outputs
	P3OUT				=	0;					// All P3.x reset
	P4DIR				=	0xFF;				// All P4.x outputs
	P4OUT				=	0;					// All P4.x reset
	
	// set the baud to 4800, see device family guide
	UCA1BR0				=	0x06;				
	UCA1BR1				=	0x00;
	UCA1MCTL			=	UCBRS2 + UCBRS1 + UCBRS0;
	
	UCA1CTL1			&=	~UCSWRST;			// release the UART
	UC1IE_bit.UCA1TXIE	=	1;					// enable TX interrupt
	
	__enable_interrupt();
	
	for (;;)
		__low_power_mode_3();
}

#pragma vector = USCIAB1TX_VECTOR
__interrupt void USCIAB1TX_ISR (void)
{
	if (txBufferPos == txBufferSize)
		checkState();
	else
		UCA1TXBUF = txBuffer[txBufferPos++];				 // TX next character
}
